﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "PropertyInstanceSetting.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
namespace PropertyWidget
{
    CPropertyItem::CPropertyItem(int uniqueID, const QString& name, const QString& description, const QVariant& value, int index, bool isEnable/* = true*/,
        GEditStyle editStyle/* = esSimple*/, bool bCanBindToOther/* = false*/,  CPropertyGroupItem* pGroupItem/* = 0*/)
        : m_uniqueID(uniqueID), m_name(name), m_itemDesp(description), m_value(value),m_index(index)
        , m_isEnable(isEnable), m_editStyle(editStyle), m_bCanBind(bCanBindToOther), m_groupItem(pGroupItem)
        , m_isMultiVal(false) //,m_ComboboxCurrentIndex(0)
        , m_isModifiable(false)
    {
    }

    CPropertyItem::~CPropertyItem()
    {
    }

    void CPropertyItem::SetName(const QString& name)
    {
        m_name = name;
    }

    const QString& CPropertyItem::GetName() const
    {
        return m_name;
    }

    void CPropertyItem::SetOriginParamName(const QString& name)
    {
        m_originParamName = name;
    }

    const QString& CPropertyItem::GetOriginParamName() const
    {
        return m_originParamName;
    }

    int CPropertyItem::Index() const
    {
        return m_index;
    }

    int CPropertyItem::UniqueID() const
    {
        return m_uniqueID;
    }

    bool CPropertyItem::SetValue(const QVariant& value)
    {
        m_value = value;
        return true;
    }

    const QVariant& CPropertyItem::GetValue() const
    {
        if (m_editStyle != esBool && m_isMultiVal)
        {
            const_cast<QVariant&>(m_value) = GetMultiValueString();
        }
        return m_value;
    }

    void CPropertyItem::SetDescription(const QString& description)
    {
        m_itemDesp = description;
    }

    QString CPropertyItem::GetDescription() const
    {
        return m_itemDesp;
    }

    void CPropertyItem::SetEditStyle(GEditStyle editStyle)
    {
        m_editStyle = editStyle;
    }

    GEditStyle CPropertyItem::GetEditStyle() const
    {
        return m_editStyle;
    }

    CPropertyGroupItem *CPropertyItem::GetGroupItem() const
    {
        return m_groupItem;
    }

    void CPropertyItem::SetEnable(bool isEnable)
    {
        m_isEnable = isEnable;
    }

    bool CPropertyItem::IsEnable() const
    {
        return m_isEnable;
    }

    void CPropertyItem::SetManualInputModifiable(bool bIsModifiable)
    {
        m_isModifiable = bIsModifiable;
    }
    bool CPropertyItem::IsManualInputModifiable() const
    {
        return m_isModifiable;
    }

    void CPropertyItem::SetComboboxItems(const QStringList& rItems)
    {
        m_comboboxItems = rItems;
    }

    const QStringList& CPropertyItem::GetComboboxItems()const
    {
        if (m_isMultiVal)
        {
            const_cast<QStringList&>(m_comboboxItems).push_back(GetMultiValueString());
        }
        return m_comboboxItems;
    }

    void CPropertyItem::SetGroupItem(CPropertyGroupItem *pGroupItem)
    {
        m_groupItem = pGroupItem;
    }

    void CPropertyItem::SetIndex(int index)
    {
        m_index = index;
    }
    void CPropertyItem::SetCanBindToOther(bool bCanBind)
    {
        m_bCanBind = bCanBind;
    }
    bool CPropertyItem::CanBind()
    {
        return m_bCanBind;
    }

    void CPropertyItem::SetIsMultiValue(bool isMultiVal)
    {
        m_isMultiVal = isMultiVal;
    }
    bool CPropertyItem::IsMultiValue() const
    {
        return m_isMultiVal;
    }

    //////////////////////////////////////////////////////////////////////////
    // CPropertyGroupItem
    CPropertyGroupItem::CPropertyGroupItem(int groupIndex, int uniqueID, const QString& name, const QString& description)
        :CPropertyItem(uniqueID, name, description,"",-1,false, esNone, 0)
    {
        m_groupIndex = groupIndex;
    }

    CPropertyGroupItem::~CPropertyGroupItem()
    {
    }

    int CPropertyGroupItem::GetGroupIndex() const
    {
        return m_groupIndex;
    }

    CPropertyItem* CPropertyGroupItem::InsertPropertyItem(int index, int uniqueID, const QString& name, const QString& description, 
        const QVariant& value, bool isEnable, GEditStyle editStyle, bool bCanbeBind)
    {
        if (name.isEmpty() || index < 0)
        {
            return nullptr;
        }

        std::unique_ptr<CPropertyItem> upNewItem = std::unique_ptr<CPropertyItem>(new CPropertyItem(uniqueID, name, description, value, index, isEnable, editStyle, bCanbeBind, this));
        if (index >= (int)m_propertyItems.size())
        {
            m_propertyItems.push_back(std::move(upNewItem));
            return m_propertyItems.back().get();
        }
        else
        {
            m_propertyItems.insert(m_propertyItems.begin() + index, std::move(upNewItem));
            for (int i = index + 1; i < (int)m_propertyItems.size(); i++)
            {
                CPropertyItem* pTmpItem = m_propertyItems[i].get();
                pTmpItem->SetIndex(i);
            }
            return m_propertyItems[index].get();
        }
    }

    CPropertyItem* CPropertyGroupItem::AddPropertyItem(int uniqueID, const QString& name, const QString& description, const QVariant& value, 
        bool isEnable, GEditStyle editStyle, bool bCanbeBind)
    {
        if (name.isEmpty())
        {
            return nullptr;
        }

        CPropertyItem* pItem = InsertPropertyItem((int)m_propertyItems.size(), uniqueID, name, description, value, isEnable, editStyle, bCanbeBind);
        return pItem;
    }

    CPropertyItem* CPropertyGroupItem::Item(int index)const
    {
        if (index < 0 || index >= (int)m_propertyItems.size())
        {
            return 0;
        }
        return m_propertyItems.at(index).get();
    }

    CPropertyItem* CPropertyGroupItem::Item(const QString& name)
    {
        if (name.isEmpty())
        {
            return nullptr;
        }
        for (int i = 0; i < (int)m_propertyItems.size(); i++)
        {
            if (name.compare(m_propertyItems.at(i)->GetName(), Qt::CaseSensitive) == 0)
            {
                return m_propertyItems.at(i).get();
            }
        }

        return nullptr;
    }
    CPropertyItem* CPropertyGroupItem::GetItem(int uniqueID) const
    {
        for(auto itr = m_propertyItems.begin(); itr != m_propertyItems.end(); ++itr)
        {
            if((*itr)->UniqueID() == uniqueID)
            {
                return (*itr).get();
            }
        }
        return nullptr;
    }

    bool CPropertyGroupItem::RemoveItem(int index)
    {
        if (index < 0 || index >= (int)m_propertyItems.size())
        {
            return false;
        }

        std::vector<std::unique_ptr<CPropertyItem>>::iterator itr = m_propertyItems.erase(m_propertyItems.begin() + index);
        for (; itr != m_propertyItems.end(); ++itr )
        {
            (*itr)->SetIndex((*itr)->Index() - 1);
        }
        return true;
    }

    bool CPropertyGroupItem::RemoveItem(const QString& name)
    {
        CPropertyItem *pItem = Item(name);
        if (pItem)
        {
            return RemoveItem(pItem->Index());
        }
        else
        {
            return false;
        }
    }

    int CPropertyGroupItem::PropertyItemsCount() const
    {
        return static_cast<int>(m_propertyItems.size());
    }

    void CPropertyGroupItem::RemoveAllPropertyItems()
    {
        m_propertyItems.clear();
    }

    void CPropertyGroupItem::SetGroupIndex(int index)
    {
        m_groupIndex = index;
    }


    CPropertyInstanceSetting::CPropertyInstanceSetting()
    {
    }

    CPropertyInstanceSetting::~CPropertyInstanceSetting()
    {
        RemoveAllGroupItems();
    }

    CPropertyGroupItem* CPropertyInstanceSetting::InsertPropertyGroupItem(int index, int uniqueID, const QString& name, const QString& description)
    {
        //其他合法性校验todo
        if (name.isEmpty() || index < 0)
        {
            return nullptr;
        }

        std::unique_ptr<CPropertyGroupItem> upNewGroupItem = std::unique_ptr<CPropertyGroupItem>(new CPropertyGroupItem(index, uniqueID, name, description));
        if (index >= (int)m_groupItems.size())
        {
            m_groupItems.push_back(std::move(upNewGroupItem));
            return m_groupItems.back().get();
        }
        else
        {
            m_groupItems.insert(m_groupItems.begin() + index, std::move(upNewGroupItem));
            for (int i = index + 1; i < (int)m_groupItems.size(); i++)
            {
                CPropertyGroupItem* pTmpItem = m_groupItems.at(i).get();
                pTmpItem->SetGroupIndex(i);
            }
            return m_groupItems[index].get();
        }
    }

    CPropertyGroupItem* CPropertyInstanceSetting::AddPropertyGroupItem(int uniqueID, const QString& name, const QString& description)
    {
        return InsertPropertyGroupItem((int)m_groupItems.size(), uniqueID, name, description);
    }

    CPropertyGroupItem* CPropertyInstanceSetting::PropertyGroupItem(int index) const
    {
        if (index < 0 || index >= (int)m_groupItems.size())
        {
            return nullptr;
        }
        return m_groupItems.at(index).get();
    }

    CPropertyGroupItem* CPropertyInstanceSetting::PropertyGroupItem(const QString& name) const
    {
        if (name.isEmpty())
        {
            return nullptr;
        }
        for (int i = 0; i < (int)m_groupItems.size(); i++)
        {
            if (name.compare(m_groupItems.at(i)->GetName(), Qt::CaseSensitive) == 0)
            {
                return m_groupItems.at(i).get();
            }
        }
        return nullptr;
    }

    CPropertyGroupItem* CPropertyInstanceSetting::GetPropertyGroupItemByUniqueID(int uniqueID) const
    {
        int propertyGroupCount = (int)m_groupItems.size();
        for (int i = 0; i < propertyGroupCount; ++i)
        {
            if (m_groupItems.at(i)->UniqueID() == uniqueID)
            {
                return m_groupItems.at(i).get();
            }
        }
        return nullptr;
    }

    bool CPropertyInstanceSetting::RemovePropertyItem(int groupIndex, int nPropertyIndex)
    {
        if (groupIndex < 0 || nPropertyIndex < 0 || groupIndex >= (int)m_groupItems.size())
        {
            return false;
        }
        return m_groupItems.at(groupIndex)->RemoveItem(nPropertyIndex);
    }

    const CPropertyItem* CPropertyInstanceSetting::GetPropertyItem(int groupIndex, int nPropertyIndex) const
    {
        if (groupIndex < 0 || nPropertyIndex < 0 || groupIndex >= (int)m_groupItems.size())
        {
            return nullptr;
        }
        return m_groupItems.at(groupIndex)->Item(nPropertyIndex);
    }

    CPropertyItem* CPropertyInstanceSetting::GetPropertyItemByUniqueID(int uniqueID) const
    {
        int propertyGroupCount = (int)m_groupItems.size();
        for (int i = 0; i < propertyGroupCount; ++i)
        {
            int propertyCount = m_groupItems.at(i)->PropertyItemsCount();
            for (int j = 0; j < propertyCount; ++j)
            {
                CPropertyItem *pPropertyItem = m_groupItems.at(i)->Item(j);
                if (pPropertyItem->UniqueID() == uniqueID)
                {
                    return pPropertyItem;
                }
            }
        }
        return nullptr;
    }

    int CPropertyInstanceSetting::GetGroupItemsCount() const
    {
        return static_cast<int>(m_groupItems.size());
    }

    bool CPropertyInstanceSetting::RemoveAllGroupItems()
    {
        m_groupItems.clear();
        return true;
    }

    bool CPropertyInstanceSetting::RemoveGroupItem(int groupIndex)
    {
        if (groupIndex < 0 || groupIndex >= (int)m_groupItems.size())
        {
            return false;
        }

        CPropertyGroupItem *pGroupItem = m_groupItems.at(groupIndex).get();   
        std::vector<std::unique_ptr<CPropertyGroupItem>>::iterator itr = m_groupItems.erase(m_groupItems.begin() + groupIndex);
        for (; itr != m_groupItems.end(); ++itr )
        {
            (*itr)->SetGroupIndex((*itr)->GetGroupIndex() - 1);
        }
        return true;
    }
}

